﻿#ifndef QMYSQL_H
#define QMYSQL_H
#include<QString>
#include<QSqlDatabase>
#include<QSqlQuery>
#include<QStack>
#include<QSqlDriver>
#include<QScopedPointer>
#include<QSharedPointer>
class XQDatabaseData;
class XQLog;
#define XQMysqlInfo XQLog("XQMysqlInfo")
//mysql数据库
class XQMySql:public QObject
{
	Q_OBJECT
public:
	XQMySql(QObject* parent=nullptr);
	XQMySql(QString SqlName,QString host, quint16 port, QString name, QString password, QString DataBase, QObject* parent = nullptr);
	XQMySql(QString host,quint16 port,QString name ,QString password,QString DataBase, QObject* parent = nullptr);
	~XQMySql();
	//获取全局区的mysql数据库
	static XQMySql*globalInstance();
	//新的连接覆盖并获取
	static XQMySql* globalInstance(QString host, quint16 port, QString name, QString password, QString DataBase);
public:
	//拷贝数据库
	XQMySql* cloneDatabase( const QString& connectionName = QString());
	//拷贝数据库返回智能指针QScopedPointer
	QScopedPointer<XQMySql> cloneDatabase_ScopedPointer(const QString& connectionName=QString());
	//拷贝数据库返回智能指针QSharedPointer(共享型)
	QSharedPointer<XQMySql> cloneDatabase_SharedPointer(const QString& connectionName = QString());
	//获取连接状态成功或者失败
	bool isOpen()const;
	//获取QSqlQuery
	QSqlQuery& SqlQuery();
	//获取QSqlDatabase数据库
	QSqlDatabase database()const;
	//获取错误信息
	QString error()const;
	//获取连接失败重连次数
	int reconnectionCount()const;
	//获取延迟时间
	int sleepTime()const;
public:
	//连接MySql数据库
	void connection(QString SqlName, QString host, quint16 port, QString name, QString password, QString DataBase);
	//添加服务器的主机地址和端口
	void addHostPort(QString host, quint16 port);
	//删除一个主机
	void removeHostPort(QString host);
	//设置连接失败重连次数
	void setReconnectionCount(int count);
	//设置延迟时间
	void setSleepTime(int sleep);
public:
	//执行sql命令
	bool Query(const QString& query, const QVariantList& values = QVariantList());
	//创建表
	bool createTable(XQDatabaseData* database,const QString& tableName);
	//删除表
	bool deleteTable(const QString& tableName);
public:
	//获取32位uuid
	QString uuid(const QString& variate=QString());
	//获取服务器当前时间
	QDateTime ctime(const QString& variate = QString());
public:
	//获取结果
	bool result();//只判断是否有结果
	//只获取指定列的数据
	bool result(QVariant& ret,int nSel=0);
	//获取一行
	bool result(QVariantList& ret);
	//获取一列进栈
	bool result(QStack<QVariant>& ret);
	//获取返回的所有数据转QString
	QList<QStringList> result_all_toString();
	//获取返回的所有数据
	QList<QVariantList> result_all();
	//获取一列全部数据转QString
	QStringList  result_oneColumn_toString(int nSel = 0);
	//获取一列全部数据
	QVariantList result_oneColumn(int nSel = 0);
	//获取第一行全部数据转QString
	QStringList  result_oneRow_toString();
	//获取第一行全部数据
	QVariantList result_oneRow();
	//获取一个数据转QString
	QString result_one_toString();
	//获取一个数据
	QVariant result_one();
public:
	//查询指定表名是否存在
	bool tabelExists(const QString& tableName);
	//查询表内的行数
	qint64 SELECT_COUNT(const QString& tableName, const QString& Where = QString(), const QVariantList& WhereBindValues = QVariantList());
	//查询数据
	bool SELECT(const QString& tableName, const QStringList& fields, const QString& rightSql = QString(),const QVariantList& rightSqlBindValues= QVariantList());
	bool SELECT_Where(const QString& tableName, const QStringList& fields, const QString& Where = QString(), const QVariantList& WhereBindValues = QVariantList());
	//查询数据 XQDatabaseData
	bool SELECT_Where(const QString& tableName, const QStringList& fields, XQDatabaseData* receive, const QString& Where, const QVariantList& WhereBindValues);
	//查询表的所有字段
	QStringList fieldList(const QString& tableName);
	//查询指定字段的所有数据
	QVariantList findData(const QString& tableName, const QString& field, const QString& Where = QString(), const QVariantList& WhereBindValues = QVariantList());
	QList<QVariantMap> findData_toVariantMap(const QString& tableName, const QString& field, const QString& Where = QString(), const QVariantList& WhereBindValues = QVariantList());
	//查询指定字段的所有数据转QString
	QStringList findData_toString(const QString& tableName, const QString& field);
	//查询指定字段合集的所有数据
	QList<QVariantList> findDatas(const QString& tableName, const QStringList& fields, const QString& Where=QString(), const QVariantList& WhereBindValues = QVariantList());
	QList<QVariantMap> findDatas_toVariantMap(const QString& tableName, const QStringList& fields, const QString& Where = QString(), const QVariantList& WhereBindValues = QVariantList());
	//查询指定字段合集的所有数据转QString
	QList<QStringList> findDatas_toString(const QString& tableName, const QStringList& fields);
	//查询表所有数据
	QList<QVariantList> findDataAll(const QString& tableName);
	//查询表所有数据转QString
	QList<QStringList> findDataAll_toString(const QString& tableName);
public:
	//插入数据
	bool INSERT(const QString& tableName, const QStringList& fields,const QVariantList& insertDatas);
	//插入数据 QVariantMap
	bool INSERT(const QString& tableName, const QVariantMap& data);
	//插入数据 XQDatabaseData
	bool INSERT(const QString& tableName, const QStringList& fields, XQDatabaseData* data);
	//批量插入
	bool INSERTS(const QString& tableName, const QStringList& fields,const QList<QVariantList>& insertDatas);
	//批量插入 XQDatabaseData
	bool INSERTS(const QString& tableName, const QStringList& fields, const QList<XQDatabaseData*>& insertDatas);
public:
	//更新数据
	bool UPDATE(const QString& tableName,const QStringList& fields,const QVariantList& insertDatas,const QString& Where = QString(), const QVariantList& WhereBindValues = QVariantList());
	//更新数据 QVariantMap
	bool UPDATE(const QString& tableName, const QVariantMap& data, const QString& Where = QString(), const QVariantList& WhereBindValues = QVariantList());
	//更新数据 XQDatabaseData
	bool UPDATE(const QString& tableName, const QStringList& fields, XQDatabaseData* data, const QString& Where = QString(), const QVariantList& WhereBindValues = QVariantList());
public:
	//删除数据
	bool DELETE(const QString& tableName,const QString& Where, QVariantList&& values);
signals:
	//命令错误发生
	void sqlError(const QString& error);
	//连接mysql成功
	void connectionSucceed();
protected:
	void init();
	//打开数据库 重连次数 延迟时间秒
	bool openDatabase(QSqlDatabase& database,int count=0,int sleep=5);
private:
	static XQMySql* m_mysql;//全局默认mysql
	static XQLog* m_log;//mysql全局日志
	QMap<QString,quint16> m_hostPort;//主机和端口列表
	QString m_SqlName;
	QSqlQuery m_sqlQuery;
	int m_reconnectionCount = 0;//重连次数
	int m_sleepTime = 5;//延迟时间
};
////格式转化递归
//template <typename _Ty, typename ...Args>
//void format(const QStringList& ret,int nSel, _Ty&& data, Args&& ...args);
////插入表数据
//void _insertStringList(QStringList& list, const char* data);
//void _insertStringList(QStringList& list, const QString data);
//template<typename _Ty>
//inline void _insertStringList(QStringList& list, _Ty  data)
//{
//	list << QString("%1").arg(data);
//}
//template <typename _Ty, typename ...Args>
//inline void _insertStringList(QStringList& list,_Ty data, Args&& ...args)
//{
//	_insertStringList(list, data);
//	_insertStringList(list, std::forward<Args>(args)...);
//}
////插入全部表数据
//void _insertStringListAll(QStringList& list, const char* data);
//void _insertStringListAll(QStringList& list, const QString data);
//template<typename _Ty>
//inline void _insertStringListAll(QStringList& list, _Ty  data)
//{
//	list << QString("%1").arg(data);
//}
//template <typename _Ty, typename ...Args>
//inline void _insertStringListAll(QStringList& list, _Ty data, Args&& ...args)
//{
//	_insertStringListAll(list, data);
//	_insertStringListAll(list, std::forward<Args>(args)...);
//}
//
//
////SQL语句组合
//template <typename _Ty>
//inline void QStringArgs(QString& str, _Ty&& data)
//{
//	str = str.arg(data);
//}
//template <typename _Ty, typename ...Args>
//inline void QStringArgs(QString& str, _Ty&& data, Args&& ...args)
//{
//	str = str.arg(data);
//	QStringArgs(str, std::forward<Args>(args)...);
//}
//template<typename _Ty, typename ...Args>
//inline void format(const QStringList& ret, int nSel, _Ty&& data, Args && ...args)
//{
//	format(ret[nSel], data);//格式转化
//	format(ret, nSel + 1, std::forward<Args>(args)...);//递归解包
//}
#endif


